﻿using System;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using DbManager;
using DbManager.DataManager;
using DbManager.QueryBuilder.DataManagment.Options;
using DbManager.QueryBuilder.DbEntity;
using DbManager.QueryBuilder.DbEntity.Bron;
using DbManager.QueryBuilder.DbEntity.Group;
using DbManager.QueryBuilder.DbEntity.Pol;
using DbManager.QueryBuilder.DbEntity.Pot;
using DbManager.QueryBuilder.DbEntity.Price;
using DbManager.QueryBuilder.DbEntity.Viezd;

namespace TAProject.UI.Order
{
    public partial class FormTourPrice : FormTemplate
    {
        private readonly IConnectionManager _connectionManager;
        private readonly IDataManager _dataManager;
        private readonly AEntityBron _aEntityBron;
        private readonly AEntityGroup _aEntityGroup;
        private readonly AEntityPrice _aEntityPrice;
        private readonly AEntityViezd _aEntityViezd;
        private readonly IDataManagmentOptions _dataManagmentDiscount;
        private readonly IDataManagmentOptions _dataManagmentInsurance;

        private readonly decimal? _discount;
        private readonly decimal? _insurance;

        private readonly bool _isUpdate;
        private readonly Form _parentParentForm;
        private readonly Form _parentForm;

        private int _quantityAdult;
        private int _quantityChild;

        private readonly DataTable _dataTableGroup;

        public FormTourPrice(Form parentParentForm, Form parentForm, AEntityBron aEntityBron, IDataManager dataManager,
                             IConnectionManager connectionManager, AEntityViezd aEntityViezd,
                             AEntityPrice aEntityPrice, DataTable dataTableGroup, bool isUpdate)
            : base(parentForm)
        {
            InitializeComponent();

            _parentForm = parentForm;
            _parentParentForm = parentParentForm;
            _dataManager = dataManager;
            _connectionManager = connectionManager;
            _aEntityBron = aEntityBron;
            _aEntityPrice = aEntityPrice;
            _aEntityViezd = aEntityViezd;
            _dataTableGroup = dataTableGroup;
            _isUpdate = isUpdate;

            _aEntityGroup = new EntityGroup {IDGroup = _aEntityBron.IDGroup};

            _dataManagmentDiscount = new DataManagmentDiscount();
            _dataManagmentInsurance = new DataManagmentInsurance();

            _parentForm.Enabled = false;

            TryGetDataWrapper(_aEntityBron.Insurance, ref _insurance, _dataManagmentInsurance, "страховке");
            TryGetDataWrapper(_aEntityBron.Discount, ref _discount, _dataManagmentDiscount, "скидке");

            _insurance = _insurance*100; //преобразовать из процентов в число

            CountGroupAc();
            FillForm();
        }

        private void TryGetDataWrapper(bool predicate, ref decimal? targetValue, IDataManagmentOptions option, string message)
        {
            if (predicate)
            {
                targetValue = TryGetData(option);
                if (targetValue == null)
                {
                    MessageBox.Show("Ошибка получения данных о " + message + ".");
                    FormClose();
                }
            }
        }

        private decimal? TryGetData(IDataManagmentOptions dataManagmentOptions)
        {
            var value = _dataManager.GetItemStringById(dataManagmentOptions.GetSelectQuery(),
                                                       _connectionManager.GetConnection());

            if (!string.IsNullOrEmpty(value))
            {
                try
                {
                    return decimal.Parse(value.Replace(".", ","));
                }
                catch (Exception)
                {
                    MessageBox.Show("Ошибка распознавания данных.");
                }
            }
            else
            {
                MessageBox.Show("Ошибка получения данных из БД");
                FormClose();
            }

            return null;
        }

        private void ButtonSubmitClick(object sender, EventArgs e)
        {
            if (_aEntityPrice.ID == 0 || _aEntityViezd.ID == 0) return;
            if (ReadyTextBox())
            {
                var entityGroup = new EntityGroup {IDGroup = _aEntityBron.IDGroup};
                if (_isUpdate)
                {
                    foreach (DataRow row in _dataTableGroup.Rows)
                    {
                        if(row.RowState == DataRowState.Deleted)
                        {
                            entityGroup.ID = (int)row["Идентификатор", DataRowVersion.Original];
                            _dataManager.ManageDataInDb(new EntityGroupSingle {ID = entityGroup.ID}.GetDeleteQuery(),
                                                        _connectionManager.GetConnection());
                            continue;
                        }

                        if(row.RowState == DataRowState.Added)
                        {
                            entityGroup.Surname = row["Фамилия"].ToString();
                            entityGroup.Name = row["Имя"].ToString();
                            entityGroup.FatherName = row["Отчество"].ToString();
                            entityGroup.IsChild = (bool)row["Ребенок"];

                            _dataManager.ManageDataInDb(entityGroup.GetInsertQuery(), _connectionManager.GetConnection());
                            continue;
                        }

                        entityGroup.ID = (int)row["Идентификатор"];
                        entityGroup.Surname = row["Фамилия"].ToString();
                        entityGroup.Name = row["Имя"].ToString();
                        entityGroup.FatherName = row["Отчество"].ToString();
                        entityGroup.IsChild = (bool)row["Ребенок"];

                        _dataManager.ManageDataInDb(entityGroup.GetUpdateQuery(), _connectionManager.GetConnection());
                    }

                    int rowAffectedBron = _dataManager.ManageDataInDb(_aEntityBron.GetUpdateQuery(),
                                                                      _connectionManager.GetConnection());
                    int rowAffectedPrice = _dataManager.ManageDataInDb(_aEntityPrice.GetUpdateQuery(),
                                                                       _connectionManager.GetConnection());
                    int rowAffectedViezd = _dataManager.ManageDataInDb(_aEntityViezd.GetUpdateQuery(),
                                                                       _connectionManager.GetConnection());

                    if (rowAffectedBron == 0 || rowAffectedPrice == 0 || rowAffectedViezd == 0)
                    {
                        MessageBox.Show("Ошибка выполнения запроса. бронь/цена/выезд");
                        MessageBox.Show(_aEntityBron.GetUpdateQuery());
                        MessageBox.Show(_aEntityViezd.GetUpdateQuery());
                        MessageBox.Show(_aEntityPrice.GetUpdateQuery());
                    }
                    else
                    {
                        ((MainForm) _parentParentForm).InvokeDataGridBronUpdate();
                        _parentForm.Close();
                        Close();
                    }
                }
                else
                {
                    foreach (DataRow row in _dataTableGroup.Rows)
                    {
                        entityGroup.Surname = row["Фамилия"].ToString();
                        entityGroup.Name = row["Имя"].ToString();
                        entityGroup.FatherName = row["Отчество"].ToString();
                        entityGroup.IsChild = (bool) row["Ребенок"];

                        _dataManager.ManageDataInDb(entityGroup.GetInsertQuery(), _connectionManager.GetConnection());
                    }

                    int rowAffectedBron = _dataManager.ManageDataInDb(_aEntityBron.GetInsertQuery(),
                                                                      _connectionManager.GetConnection());
                    int rowAffectedPrice = _dataManager.ManageDataInDb(_aEntityPrice.GetInsertQuery(),
                                                                       _connectionManager.GetConnection());
                    int rowAffectedViezd = _dataManager.ManageDataInDb(_aEntityViezd.GetInsertQuery(),
                                                                       _connectionManager.GetConnection());

                    if (rowAffectedBron == 0 || rowAffectedPrice == 0 || rowAffectedViezd == 0)
                    {
                        MessageBox.Show("Ошибка выполнения запроса. бронь/цена/выезд");
                        MessageBox.Show(_aEntityBron.GetInsertQuery());
                        MessageBox.Show(_aEntityViezd.GetInsertQuery());
                        MessageBox.Show(_aEntityPrice.GetInsertQuery());
                    }
                    else
                    {
                        ((MainForm)_parentParentForm).InvokeDataGridBronUpdate();
                        _parentForm.Close();
                        Close();
                    }
                }
            }
            else
            {
                MessageBox.Show("Одно из полей заполнено некорректно. Проверьте помеченные поля.");
            }
        }

        private void ButtonCancelClick(object sender, EventArgs e)
        {
            FormClose();
        }

        private void FormClose()
        {
            _parentForm.Enabled = true;
            Close();
        }

        private void FillForm()
        {
            AEntityPot aEntityPotSingle = new EntityPotSingle {ID = _aEntityBron.IDPot};
            AEntityPol aEntityPolSingle = new EntityPolSingle {ID = _aEntityBron.IDPol};

            try
            {
                var dataTable = _dataManager.GetDataTable(aEntityPotSingle.GetSelectQuery(),
                                                          _connectionManager.GetConnection());

                var tarifProezdChild = decimal.Parse(dataTable.Rows[0]["Цена ребенок"].ToString());
                var tarifProezdAdult = decimal.Parse(dataTable.Rows[0]["Цена взрослый"].ToString());

                dataTable = _dataManager.GetDataTable(aEntityPolSingle.GetSelectQuery(),
                                                      _connectionManager.GetConnection());

                var tarifProjivania = decimal.Parse(dataTable.Rows[0]["Цена"].ToString());

                _aEntityPrice.Proezd = Math.Round(_quantityAdult*tarifProezdAdult + _quantityChild*tarifProezdChild, 2);
                _aEntityPrice.Projivanie = Math.Round(_aEntityBron.LongOfRest*tarifProjivania, 2);

                _aEntityPrice.DiscountProezd = Math.Round((_aEntityPrice.Proezd * (_discount != null ? _discount.Value : 0)), 2);
                _aEntityPrice.Insurance = Math.Round((_quantityAdult + _quantityChild) * (_insurance != null ? _insurance.Value : 0), 2);

                _aEntityPrice.VsegoKOplate = Math.Round((_aEntityPrice.Proezd - _aEntityPrice.DiscountProezd) +
                                                    (_aEntityPrice.Projivanie - _aEntityPrice.DiscountProjivanie) +
                                                    _aEntityPrice.Insurance + _aEntityPrice.Transfer + _aEntityPrice.Bron, 2);

                textBoxCenaProezd.Text = _aEntityPrice.Proezd.ToString();
                textBoxCenaProjivanie.Text = _aEntityPrice.Projivanie.ToString();
                textBoxDiscoountProezd.Text = _aEntityPrice.DiscountProezd.ToString();
                textBoxInsurance.Text = _aEntityPrice.Insurance.ToString();

                textBoxDiscountProjivanie.Text = (Math.Round(_aEntityPrice.DiscountProjivanie, 2)).ToString();
                textBoxTransfer.Text = (Math.Round(_aEntityPrice.Transfer, 2)).ToString();
                textBoxBron.Text = (Math.Round(_aEntityPrice.Bron, 2)).ToString();
                textBoxOplachenoProezd.Text = (Math.Round(_aEntityPrice.OplachenoProezd, 2)).ToString();
                textBoxOplachenoProjivanie.Text = (Math.Round(_aEntityPrice.OplachenoProjivanie, 2)).ToString();

                textBoxKOplateProezd.Text =
                    Math.Round(
                        (_aEntityPrice.Proezd + _aEntityPrice.Insurance + _aEntityPrice.Transfer -
                         _aEntityPrice.DiscountProezd), 2).ToString();
                textBoxKOplateProjivanie.Text =
                    Math.Round(
                        (_aEntityPrice.Projivanie - _aEntityPrice.DiscountProjivanie + _aEntityPrice.Bron),
                        2).ToString();
                textBoxKOplateVsego.Text = Math.Round(_aEntityPrice.VsegoKOplate, 2).ToString();
                ReCalculate();
            }
            catch (Exception)
            {
                MessageBox.Show("Ошибка получения данных из БД.");
            }
        }

        private void TextBoxOplachenoProezdTextChanged(object sender, EventArgs e)
        {
            _aEntityPrice.OplachenoProezd = ReadValueFromTextBox(textBoxOplachenoProezd);
            ReCalculate();
        }

        private void TextBoxOplachenoProjivanieTextChanged(object sender, EventArgs e)
        {
            _aEntityPrice.OplachenoProjivanie = ReadValueFromTextBox(textBoxOplachenoProjivanie);
            ReCalculate();
        }

        private void TextBoxTransferTextChanged(object sender, EventArgs e)
        {
            _aEntityPrice.Transfer = ReadValueFromTextBox(textBoxTransfer);
            ReCalculate();
        }

        private void TextBoxBronTextChanged(object sender, EventArgs e)
        {
            _aEntityPrice.Bron = ReadValueFromTextBox(textBoxBron);
            ReCalculate();
        }

        private void TextBoxDiscountProjivanieTextChanged(object sender, EventArgs e)
        {
            _aEntityPrice.DiscountProjivanie = ReadValueFromTextBox(textBoxDiscountProjivanie);
            ReCalculate();
        }

        private void ReCalculate()
        {
            textBoxOstatokProezd.Text =
                Math.Round((_aEntityPrice.Proezd + _aEntityPrice.Insurance + _aEntityPrice.Transfer -
                            _aEntityPrice.DiscountProezd - _aEntityPrice.OplachenoProezd), 2).ToString();
            textBoxOstatokProjivanie.Text =
                Math.Round((_aEntityPrice.Projivanie - _aEntityPrice.DiscountProjivanie -
                            _aEntityPrice.OplachenoProjivanie + _aEntityPrice.Bron), 2).ToString();
            textBoxKOplateProezd.Text =
                Math.Round((_aEntityPrice.Proezd + _aEntityPrice.Insurance + _aEntityPrice.Transfer -
                            _aEntityPrice.DiscountProezd), 2).ToString();
            textBoxKOplateProjivanie.Text =
                Math.Round((_aEntityPrice.Projivanie - _aEntityPrice.DiscountProjivanie + _aEntityPrice.Bron), 2).
                    ToString();
            _aEntityPrice.VsegoKOplate = Math.Round((_aEntityPrice.Proezd - _aEntityPrice.DiscountProezd) +
                                                    (_aEntityPrice.Projivanie - _aEntityPrice.DiscountProjivanie) +
                                                    _aEntityPrice.Insurance + _aEntityPrice.Transfer + _aEntityPrice.Bron, 2);
            textBoxKOplateVsego.Text = Math.Round(_aEntityPrice.VsegoKOplate, 2).ToString();
        }

        private void CountGroupAc()
        {
            _quantityAdult = _dataTableGroup.AsEnumerable().Count(row => row.RowState != DataRowState.Deleted && row.Field<bool>("Ребенок") == false) + 1; // '+1' добавляем заказчика
            _quantityChild = _dataTableGroup.AsEnumerable().Count(row => row.RowState != DataRowState.Deleted && row.Field<bool>("Ребенок"));
        }

        private static decimal ReadValueFromTextBox(Control textBox)
        {
            try
            {
                var result = decimal.Parse(textBox.Text.Replace(".", ","));
                textBox.BackColor = SystemColors.Window;
                return result;
            }
            catch
            {
                textBox.BackColor = Color.FromArgb(255, 230, 230);
            }
            return 0;
        }

        private bool ReadyTextBox()
        {
            if (textBoxOplachenoProezd.BackColor == Color.FromArgb(255, 230, 230) ||
                textBoxOplachenoProjivanie.BackColor == Color.FromArgb(255, 230, 230) ||
                textBoxTransfer.BackColor == Color.FromArgb(255, 230, 230) ||
                textBoxBron.BackColor == Color.FromArgb(255, 230, 230) ||
                textBoxDiscountProjivanie.BackColor == Color.FromArgb(255, 230, 230))
            {
                return false;
            }
            return true;
        }
    }
}